import numpy as np


def signal(*args):
    df = args[0]
    n = args[1]
    factor_name = args[2]

    df["median"] = df["close"].rolling(n).mean()
    df["std"] = df["close"].rolling(n).std(ddof=0)
    df["upper"] = df["median"] + 2 * df["std"]
    df["lower"] = df["median"] - 2 * df["std"]
    df["count"] = 0
    df.loc[df["close"] > df["upper"], "count"] = (df["close"] - df["upper"]) / df["close"]
    df.loc[df["close"] < df["lower"], "count"] = (df["close"] - df["lower"]) / df["close"]


    #【FREESTEP】对暴涨暴跌币的惩罚因子的尝试https://bbs.quantclass.cn/thread/21419
    h1_change = df["close"].pct_change().fillna(0).abs()
    max_h1_change = h1_change.rolling(24, min_periods=1).max()
    punish = np.where(max_h1_change < 0.1, 1, 1 + (10 * max_h1_change - 1) ** 5)

    df[factor_name] = df["count"].rolling(n).sum() / punish

    del df["median"]
    del df["std"]
    del df["upper"]
    del df["lower"]
    del df["count"]

    return df